// #pragma once
// #include<iostream>
// #include<vector>
// #include<cassert>
// #include<semaphore.h>//信号量头文件
// #include<pthread.h>

// static const int gcap = 5;

// template<class T>
// class RingQueue
// {
// private:
//     void P(sem_t &sem)
//     {
//         int n = sem_wait(&sem);
//         assert(n == 0);// if
//         (void)n;
//     }
//     void V(sem_t &sem)
//     {
//         int n = sem_post(&sem);
//         assert(n == 0);
//         (void)n;
//     }
// public:
//     RingQueue(const int &cap = gcap): _queue(cap), _cap(cap)
//     {
//         int n = sem_init(&_spaceSem, 0, _cap);//信号量初始化的值为_cap
//         assert(n == 0);
//         n = sem_init(&_dataSem, 0, 0);
//         assert(n == 0);
//         _productorStep = _consumerStep = 0;
//     }

//     //生产者
//     void Push(const T& in)
//     {
//         P(_spaceSem); // 申请到了空间信号量，意味着，我一定能进行正常的生产
//         _queue[_productorStep++] = in;
//         _productorStep %= _cap;
//         V(_dataSem);
//     }
//     //消费者
//     void Pop(T* out)//输出型参数
//     {
//         P(_dataSem);
//         *out = _queue[_consumerStep++];//改1
//         _consumerStep %= _cap;
//         V(_spaceSem);//空间多了一个
//     }

//     ~RingQueue()
//     {
//         sem_destroy(&_spaceSem);
//         sem_destroy(&_dataSem);
//     }
// private:
//     std::vector<T> _queue;
//     int _cap;
//     sem_t _spaceSem; //productor want product, 看中的是空间资源
//     sem_t _dataSem;  //consumer want consume, 看中的是数据资源

//     int _productorStep;
//     int _consumerStep;
// };

// // 01:15:43

#pragma once

#include <iostream>
#include <vector>
#include <cassert>
#include <semaphore.h>
#include <pthread.h>

static const int gcap = 5000;

template<class T>
class RingQueue
{
private:
    void P(sem_t &sem)
    {
        int n = sem_wait(&sem);
        assert(n == 0); // if
        (void)n;
    }
    void V(sem_t &sem)
    {
        int n = sem_post(&sem);
        assert(n == 0);
        (void)n;
    }
public:
    RingQueue(const int &cap = gcap): _queue(cap), _cap(cap)
    {
        int n = sem_init(&_spaceSem, 0, _cap);
        assert(n == 0);
        n = sem_init(&_dataSem, 0, 0);
        assert(n == 0);

        _productorStep = _consumerStep = 0;

        //pthread_mutex_init(&_pmutex, nullptr);
        //pthread_mutex_init(&_cmutex, nullptr);
    }
    // 生产者
    void Push(const T &in)
    {
        // ?: 这个代码 有没有优化的可能
        // 你认为：现加锁，后申请信号量，还是现申请信号量，在加锁？
        P(_spaceSem); // 申请到了空间信号量，意味着，我一定能进行正常的生产
        pthread_mutex_lock(&_pmutex);        
        _queue[_productorStep++] = in;
        _productorStep %= _cap;
        pthread_mutex_unlock(&_pmutex);
        V(_dataSem);
    }
    // 消费者
    void Pop(T *out)
    {
        // 你认为：现加锁，后申请信号量，还是现申请信号量，在加锁？
        P(_dataSem);
        pthread_mutex_lock(&_cmutex);
        *out = _queue[_consumerStep++];
        _consumerStep %= _cap;
        pthread_mutex_unlock(&_cmutex);
        V(_spaceSem);
    }
    ~RingQueue()
    {
        sem_destroy(&_spaceSem);
        sem_destroy(&_dataSem);

        pthread_mutex_destroy(&_pmutex);
        pthread_mutex_destroy(&_cmutex);
    }
private:
    std::vector<T> _queue;
    int _cap;
    sem_t _spaceSem; // 生产者 想生产，看中的是什么资源呢? 空间资源
    sem_t _dataSem;  // 消费者 想消费，看中的是什么资源呢? 数据资源
    int _productorStep;
    int _consumerStep;
    pthread_mutex_t _pmutex;
    pthread_mutex_t _cmutex;
};

